//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  http://www.nopCommerce.com/License.aspx. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations under the License.
// 
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
// 
// Contributor(s): _______. 
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Security;
using System.Web;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Web.UI.WebControls;
using System.Globalization;
using Tathata.Common.BLL.Enums;
using Tathata.Common.BLL.Entities;
using Tathata.Common.BLL.Managers;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Security.Cryptography;
using System.IO;
using Tathata.Common.Configuration;
using System.Xml;

namespace Tathata.Common.Utils
{
    /// <summary>
    /// Represents a common helper
    /// </summary>
    public class CommonHelper
    {
        #region Methods
        /// <summary>
        /// Verifies that a string is in valid e-mail format
        /// </summary>
        /// <param name="Email">Email to verify</param>
        /// <returns>true if the string is a valid e-mail address and false if it's not</returns>
        public static bool IsValidEmail(string Email)
        {
            return Regex.IsMatch(Email, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }

        /// <summary>
        /// Gets query string value by name
        /// </summary>
        /// <param name="Name">Parameter name</param>
        /// <returns>Query string value</returns>
        public static string QueryString(string Name)
        {
            string result = string.Empty;
            if (HttpContext.Current != null && HttpContext.Current.Request.QueryString[Name] != null)
                result = HttpContext.Current.Request.QueryString[Name].ToString();
            return result;
        }

        /// <summary>
        /// Gets boolean value from query string 
        /// </summary>
        /// <param name="Name">Parameter name</param>
        /// <returns>Query string value</returns>
        public static bool QueryStringBool(string Name)
        {
            string resultStr = QueryString(Name).ToUpperInvariant();
            return (resultStr == "YES" || resultStr == "TRUE" || resultStr == "1");
        }

        /// <summary>
        /// Gets integer value from query string 
        /// </summary>
        /// <param name="Name">Parameter name</param>
        /// <returns>Query string value</returns>
        public static int QueryStringInt(string Name)
        {
            string resultStr = QueryString(Name).ToUpperInvariant();
            int result;
            Int32.TryParse(resultStr, out result);
            return result;
        }

        /// <summary>
        /// Gets GUID value from query string 
        /// </summary>
        /// <param name="Name">Parameter name</param>
        /// <returns>Query string value</returns>
        public static Guid? QueryStringGUID(string Name)
        {
            string resultStr = QueryString(Name).ToUpperInvariant();
            Guid? result = null;
            try
            {
                result = new Guid(resultStr);
            }
            catch
            {
            }
            return result;
        }

        /// <summary>
        /// Selects item
        /// </summary>
        /// <param name="List">List</param>
        /// <param name="Value">Value to select</param>
        public static void SelectListItem(DropDownList List, object Value)
        {
            if (List.Items.Count != 0)
            {
                ListItem selectedItem = List.SelectedItem;
                if (selectedItem != null)
                    selectedItem.Selected = false;
                if (Value != null)
                {
                    selectedItem = List.Items.FindByValue(Value.ToString());
                    if (selectedItem != null)
                        selectedItem.Selected = true;
                }
            }
        }

        /// <summary>
        /// Gets server variable by name
        /// </summary>
        /// <param name="Name">Name</param>
        /// <returns>Server variable</returns>
        public static string ServerVariables(string Name)
        {
            string tmpS = String.Empty;
            try
            {
                if (HttpContext.Current.Request.ServerVariables[Name] != null)
                {

                    tmpS = HttpContext.Current.Request.ServerVariables[Name].ToString();

                }
            }
            catch
            {
                tmpS = String.Empty;
            }
            return tmpS;
        }

        /// <summary>
        /// Gets a value indicating whether requested admin page
        /// </summary>
        public static bool IsAdmin()
        {
            //TODO rewrite checking
            return GetThisPageName().ToLowerInvariant().Contains("administration/");
        }

        /// <summary>
        /// Gets this page name
        /// </summary>
        /// <returns></returns>
        public static string GetThisPageName()
        {
            string path = CommonHelper.ServerVariables("SCRIPT_NAME");
            if (path == null)
                path = string.Empty;
            return path;
        }

        /// <summary>
        /// Gets store location
        /// </summary>
        /// <param name="UseSSL">Use SSL</param>
        /// <returns>Store location</returns>
        public static string GetStoreHTTPLocation(bool UseSSL)
        {
            string s = "http://" + ServerVariables("HTTP_HOST") + HttpContext.Current.Request.ApplicationPath;
            if (!s.EndsWith("/"))
                s += "/";

            if (UseSSL)
            {
                s = s.Replace("http:/", "https:/");
                s = s.Replace("www.www", "www");
            }
            return s;
        }

        /// <summary>
        /// Gets store host location
        /// </summary>
        /// <param name="UseSSL">Use SSL</param>
        /// <returns>Store host location</returns>
        public static string GetStoreHost(bool UseSSL)
        {
            string s = "http://" + ServerVariables("HTTP_HOST");
            if (!s.EndsWith("/"))
                s += "/";

            if (UseSSL)
            {
                s = s.Replace("http:/", "https:/");
                s = s.Replace("www.www", "www");
            }
            return s;
        }

        /// <summary>
        /// Reloads current page
        /// </summary>
        public static void ReloadCurrentPage()
        {
            string storeHost = GetStoreHost(false);
            if (storeHost.EndsWith("/"))
                storeHost = storeHost.Substring(0, storeHost.Length - 1);
            string URL = storeHost + HttpContext.Current.Request.RawUrl;
            HttpContext.Current.Response.Redirect(URL);
        }

        /// <summary>
        /// Ensures that requested page is secured (https://)
        /// </summary>
        public static void EnsureSSL()
        {
            if (!HttpContext.Current.Request.IsSecureConnection)
            {
                if (SettingManager.GetSettingValueBoolean("Common.StoreHasSSLInstalled"))
                {
                    if (!HttpContext.Current.Request.Url.IsLoopback)
                    {
                        string storeHost = GetStoreHost(true);
                        if (storeHost.EndsWith("/"))
                            storeHost = storeHost.Substring(0, storeHost.Length - 1);
                        string newURL = storeHost + HttpContext.Current.Request.RawUrl;

                        HttpContext.Current.Response.Redirect(newURL);
                    }
                }
            }
        }

        /// <summary>
        /// Ensures that requested page is not secured (http://)
        /// </summary>
        public static void EnsureNonSSL()
        {
            if (HttpContext.Current.Request.IsSecureConnection)
            {
                string storeHost = GetStoreHost(false);
                if (storeHost.EndsWith("/"))
                    storeHost = storeHost.Substring(0, storeHost.Length - 1);
                string newURL = storeHost + HttpContext.Current.Request.RawUrl;

                HttpContext.Current.Response.Redirect(newURL);
            }
        }

        /// <summary>
        /// Sets cookie
        /// </summary>
        /// <param name="cookieName">Cookie name</param>
        /// <param name="cookieValue">Cookie value</param>
        /// <param name="ts">Timespan</param>
        public static void SetCookie(String cookieName, string cookieValue, TimeSpan ts)
        {
            try
            {
                HttpCookie cookie = new HttpCookie(cookieName);
                cookie.Value = HttpContext.Current.Server.UrlEncode(cookieValue);
                DateTime dt = DateTime.Now;
                cookie.Expires = dt.Add(ts);
                HttpContext.Current.Response.Cookies.Add(cookie);
            }
            catch (Exception exc)
            {
                LogManager.InsertLog(LogTypeEnum.CustomerError, exc.Message, exc.ToString());
            }
        }

        /// <summary>
        /// Gets cookie string
        /// </summary>
        /// <param name="cookieName">Cookie name</param>
        /// <param name="decode">Decode cookie</param>
        /// <returns>Cookie string</returns>
        public static String GetCookieString(String cookieName, bool decode)
        {
            if (HttpContext.Current.Request.Cookies[cookieName] == null)
            {
                return String.Empty;
            }
            try
            {
                String tmp = HttpContext.Current.Request.Cookies[cookieName].Value.ToString();
                if (decode)
                    tmp = HttpContext.Current.Server.UrlDecode(tmp);
                return tmp;
            }
            catch
            {
                return String.Empty;
            }
        }

        /// <summary>
        /// Gets boolean value from cookie
        /// </summary>
        /// <param name="cookieName">Cookie name</param>
        /// <returns>Result</returns>
        public static bool GetCookieBool(String cookieName)
        {
            String tmpS = GetCookieString(cookieName, true).ToUpperInvariant();
            return (tmpS == "TRUE" || tmpS == "YES" || tmpS == "1");
        }

        /// <summary>
        /// Gets integer value from cookie
        /// </summary>
        /// <param name="cookieName">Cookie name</param>
        /// <returns>Result</returns>
        public static int GetCookieInt(String cookieName)
        {
            String tmpS = GetCookieString(cookieName, true);
            if (!String.IsNullOrEmpty(tmpS))
                return Convert.ToInt32(tmpS);
            else
                return 0;
        }

        /// <summary>
        /// IIF
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="a">A</param>
        /// <param name="b">B</param>
        /// <returns>Result</returns>
        static public int IIF(bool condition, int a, int b)
        {
            int x = 0;
            if (condition)
                x = a;
            else
                x = b;
            return x;
        }

        /// <summary>
        /// IIF
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="a">A</param>
        /// <param name="b">B</param>
        /// <returns>Result</returns>
        static public bool IIF(bool condition, bool a, bool b)
        {
            bool x = false;
            if (condition)
                x = a;
            else
                x = b;
            return x;
        }

        /// <summary>
        /// IIF
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="a">A</param>
        /// <param name="b">B</param>
        /// <returns>Result</returns>
        static public float IIF(bool condition, Single a, Single b)
        {
            float x = 0;
            if (condition)
            {
                x = a;
            }
            else
            {
                x = b;
            }
            return x;
        }

        /// <summary>
        /// IIF
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="a">A</param>
        /// <param name="b">B</param>
        /// <returns>Result</returns>
        static public double IIF(bool condition, double a, double b)
        {
            double x = 0;
            if (condition)
            {
                x = a;
            }
            else
            {
                x = b;
            }
            return x;
        }

        /// <summary>
        /// IIF
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="a">A</param>
        /// <param name="b">B</param>
        /// <returns>Result</returns>
        static public decimal IIF(bool condition, decimal a, decimal b)
        {
            decimal x = 0;
            if (condition)
            {
                x = a;
            }
            else
            {
                x = b;
            }
            return x;
        }

        /// <summary>
        /// IIF
        /// </summary>
        /// <param name="condition">Condition</param>
        /// <param name="a">A</param>
        /// <param name="b">B</param>
        /// <returns>Result</returns>
        static public string IIF(bool condition, String a, String b)
        {
            String x = String.Empty;
            if (condition)
            {
                x = a;
            }
            else
            {
                x = b;
            }
            return x;
        }

        /// <summary>
        /// Decrypts text
        /// </summary>
        /// <param name="strCipherText">Cipher text</param>
        /// <returns>Decrypted string</returns>
        public static string Decrypt(string strCipherText)
        {
            //TODO implement decryption
            if (String.IsNullOrEmpty(strCipherText))
                return strCipherText;
            string encryptionPrivateKey = NopConfig.EncryptionPrivateKey;
            //TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider();
            //UnicodeEncoding encoding = new UnicodeEncoding();
            //ASCIIEncoding encoding2 = new ASCIIEncoding();
            //byte[] buffer = Convert.FromBase64String(strCipherText);
            //MemoryStream stream = new MemoryStream();
            //MemoryStream stream2 = new MemoryStream(buffer);
            //provider.Key = encoding2.GetBytes(encryptionPrivateKey.Substring(0, 16));
            //provider.IV = encoding2.GetBytes(encryptionPrivateKey.Substring(8, 8));
            //CryptoStream stream3 = new CryptoStream(stream2, provider.CreateDecryptor(), CryptoStreamMode.Read);
            //StreamWriter writer = new StreamWriter(stream);
            //writer.Write(new StreamReader(stream3).ReadToEnd());
            //writer.Flush();
            //stream3.Clear();
            //provider.Clear();
            //return encoding.GetString(stream.ToArray());
            //return Cryptographer.EncryptSymmetric("RijndaelManaged", strCipherText);
            return strCipherText;
        }

        /// <summary>
        /// Encrypts text
        /// </summary>
        /// <param name="strPlainText">Plaint text</param>
        /// <returns>Encrypted string</returns>
        public static string Encrypt(string strPlainText)
        {
            //TODO implement encryption
            if (String.IsNullOrEmpty(strPlainText))
                return strPlainText;
            string encryptionPrivateKey = NopConfig.EncryptionPrivateKey;
            //TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider();
            //UnicodeEncoding encoding = new UnicodeEncoding();
            //ASCIIEncoding encoding2 = new ASCIIEncoding();
            //byte[] bytes = encoding.GetBytes(strPlainText);
            //MemoryStream stream = new MemoryStream();
            //provider.Key = encoding2.GetBytes(encryptionPrivateKey.Substring(0, 16));
            //provider.IV = encoding2.GetBytes(encryptionPrivateKey.Substring(8, 8));
            //CryptoStream stream2 = new CryptoStream(stream, provider.CreateEncryptor(), CryptoStreamMode.Write);
            //stream2.Write(bytes, 0, bytes.Length);
            //stream2.FlushFinalBlock();
            //return Convert.ToBase64String(stream.ToArray());
            //return Cryptographer.DecryptSymmetric("RijndaelManaged", strPlainText);
            return strPlainText;
        }

        /// <summary>
        /// Gets boolean value from NameValue collection
        /// </summary>
        /// <param name="config">NameValue collection</param>
        /// <param name="valueName">Name</param>
        /// <param name="defaultValue">Default value</param>
        /// <returns>Result</returns>
        internal static bool ConfigGetBooleanValue(NameValueCollection config, string valueName, bool defaultValue)
        {
            bool result;
            string str1 = config[valueName];
            if (str1 == null)
                return defaultValue;
            if (!bool.TryParse(str1, out result))
                throw new ProviderException(string.Format("Value must be boolean {0}", valueName));
            return result;
        }

        /// <summary>
        /// Gets integer value from NameValue collection
        /// </summary>
        /// <param name="config">NameValue collection</param>
        /// <param name="valueName">Name</param>
        /// <param name="defaultValue">Default value</param>
        /// <param name="zeroAllowed">Zero allowed</param>
        /// <param name="maxValueAllowed">Max value allowed</param>
        /// <returns>Result</returns>
        internal static int ConfigGetIntValue(NameValueCollection config, string valueName, int defaultValue, bool zeroAllowed, int maxValueAllowed)
        {
            int result;
            string str1 = config[valueName];
            if (str1 == null)
                return defaultValue;
            if (!int.TryParse(str1, out result))
            {
                if (zeroAllowed)
                {
                    throw new ProviderException(string.Format("Value must be non negative integer {0}", valueName));
                }
                throw new ProviderException(string.Format("Value must be positive integer {0}", valueName));
            }
            if (zeroAllowed && (result < 0))
                throw new ProviderException(string.Format("Value must be non negative integer {0}", valueName));
            if (!zeroAllowed && (result <= 0))
                throw new ProviderException(string.Format("Value must be positive integer {0}", valueName));
            if ((maxValueAllowed > 0) && (result > maxValueAllowed))
                throw new ProviderException(string.Format("Value too big {0}", valueName));
            return result;
        }

        /// <summary>
        /// Write XML to response
        /// </summary>
        /// <param name="xml">XML</param>
        /// <param name="Filename">Filename</param>
        public static void WriteResponseXML(string xml, string Filename)
        {
            if (!String.IsNullOrEmpty(xml))
            {
                XmlDocument document = new XmlDocument();
                document.LoadXml(xml);
                ((XmlDeclaration)document.FirstChild).Encoding = "utf-8";
                HttpResponse response = HttpContext.Current.Response;
                response.Clear();
                response.Charset = "utf-8";
                response.ContentType = "text/xml";
                response.AddHeader("content-disposition", string.Format("attachment; filename={0}", Filename));
                response.BinaryWrite(Encoding.UTF8.GetBytes(document.InnerXml));
                response.End();
            }
        }

        #endregion
    }
}
